linux sockaddr | 您所在的位置:网站首页 › sockaddr_un 头文件 › linux sockaddr |
1、socket 不管是 Windows 还是 Linux,都使用 socket() 函数来创建套接字。socket() 在两个平台下的参数是相同的,不同的是返回值: (1)Linux 中的一切都是文件,每个文件都有一个整数类型的文件描述符;socket 也是一个文件,也有文件描述符。使用 socket() 函数创建套接字以后,返回值就是一个 int 类型的文件描述符。 (2)Windows 会区分 socket 和普通文件,它把 socket 当做一个网络连接来对待,调用 socket() 以后,返回值是 SOCKET 类型,用来表示一个套接字。 Linux 下的 socket() 函数 在 Linux 下使用 头文件中 socket() 函数来创建套接字,原型为: int socket(int af, int type, int protocol); 参数: af 为地址族(Address Family),也就是 IP 地址类型,常用的有 AF_INET 和 AF_INET6。 type 为数据传输方式/套接字类型,常用的有 SOCK_STREAM(流格式套接字/面向连接的套接字) 和 SOCK_DGRAM(数据报套接字/无连接的套接字) protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议 Linux下创建套接字: int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //IPPROTO_TCP表示TCP协议 2、sockaddr和sockaddr_in详解 struct sockaddr和struct sockaddr_in这两个结构体用来处理网络通信的地址 1、sockaddr sockaddr在头文件#include 中定义,sockaddr的缺陷是:sa_data把目标地址和端口信息混在一起了,如下: struct sockaddr { sa_family_t sin_family;//地址族 char sa_data[14]; //14字节,包含套接字中的目标地址和端口信息 }; 2、sockaddr_in sockaddr_in在头文件#include或#include 中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中,如下:
sin_port和sin_addr都必须是网络字节序(NBO),一般可视化的数字都是主机字节序(HBO)。 3、总结 二者长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。 sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址。 sockaddr_in 是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数:sockaddr_in用于socket定义和赋值;sockaddr用于函数参数。 #include #include #include #include int main(int argc,char **argv) { int sockfd; struct sockaddr_in mysock; sockfd = socket(AF_INET,SOCK_STREAM,0); //获得fd bzero(&mysock,sizeof(mysock)); //初始化结构体 mysock.sin_family = AF_INET; //设置地址家族 mysock.sin_port = htons(800); //设置端口 mysock.sin_addr.s_addr = inet_addr("192.168.1.0"); //设置地址 bind(sockfd,(struct sockaddr *)&mysock,sizeof(struct sockaddr); /* bind的时候进行转化 */ ... ... return 0; } 3、inet_addr() 描述: inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值 返回值: 若无错误发生,inet_addr()返回一个无符号长整型数,其中以适当字节顺序存放Internet地址。如果传入的字符串不是一个合法的Internet地址,如“a.b.c.d”地址中任一项超过255,那么inet_addr()返回INADDR_NONE 4、gethostbyname 函数原型: struct hostent* gethostbyname(const char *name); 调用函数成功返回一个hostent结构体 struct hostent { char *h_name; char ** h_aliases; short h_addrtype; short h_length; char ** h_addr_list; }; 测试代码: #include#include#include#include#include#include#include#include#include#include#include#include int main(int argc,char *argv[]) { int optret; char *ipname = NULL; char ip[50]; struct hostent *gethost = NULL; int file_fd; char buf[50]; char *ptrf; char *ptrb; int n; char fptr[50]; const char *ptr = NULL; struct in_addr inAddr; while((optret = getopt(argc,argv,"i:")) != -1) { switch(optret) { case 'i': ipname = optarg; printf("option = i,the ipname is:%s\n",optarg); break; } } gethost = gethostbyname(ipname); if (NULL == gethost) { perror("get ipaddr fail!"); return -1; } printf("get host successfully!\n"); memset(ip,0,sizeof(ip)); ptr = inet_ntop(gethost->h_addrtype,gethost->h_addr_list[0],ip,sizeof(ip)); printf("DNS ip is:%s\n",ptr); system("ping studio.iot-yun.com -c 2 >> /home/deepin/APUE/malunkun/test/.domain.log"); file_fd=open("/home/deepin/APUE/malunkun/test/.domain.log",O_RDONLY,644); if (file_fd < 0) { perror("open file fail!\n"); } read(file_fd,buf,sizeof(buf)); close(file_fd); ptrf = strstr(buf,"("); ptrf += 1; ptrb = strstr(buf,")"); n = strlen(ptrf)-strlen(ptrb); strncpy(fptr,ptrf,n); printf("ping ip is:%s\n",fptr); return 0; } 输出:
使用输出的IP地址去访问网站,发现显示的也是百度
5、getsockopt和setsockopt函数 这两个函数仅用于套接字。 函数原型: #include #include int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); sockfd:必须指向一个打开的套接字描述符 level:指定系统中解释选项的代码或为通用套接字代码,或为某个特定于协议的代码(例如IPv4IPv6、TCP或SCTP)。 optval:指向某个变量(*optval)的指针,setsockopt从optval中取得选项设置的新值,getsockopt则把以获取的选项当前值存入optval。 optlen:指定*optval的大小 套接字选项的汇总可以查看unix网络编程(卷1)151页 图7-1和图7-2
|
CopyRight 2018-2019 实验室设备网 版权所有 |